package com.spic.business.alarm.service.impl;

import com.spic.business.alarm.constant.CommonConstant;
import com.spic.business.alarm.domain.*;
import com.spic.business.alarm.mapper.FloodControlMapper;
import com.spic.business.alarm.mapper.WeatherDataMapper;
import com.spic.business.alarm.service.DeviceService;
import com.spic.business.alarm.service.FloodControlService;
import com.spic.business.getui.service.PushService;
import com.spic.common.core.constant.SecurityConstants;
import com.spic.common.core.domain.R;
import com.spic.common.core.utils.DateUtils;
import com.spic.common.core.utils.StringUtils;
import com.spic.system.api.RemoteNoticeInfoService;
import com.spic.system.api.RemoteUserService;
import com.spic.system.api.domain.SysNoticeInfo;
import com.spic.system.api.domain.SysUser;
import com.spic.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 防汛处置
 * @version 1.0
 * @author liujunyang
 * @date 2021/6/29 11:16
 */
@Service
public class FloodControlServiceImpl implements FloodControlService {

    @Autowired
    private ThreadPoolExecutor executor;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RemoteNoticeInfoService remoteNoticeInfoService;
    @Autowired
    private WeatherDataMapper weatherDataMapper;
    @Autowired
    private FloodControlMapper floodControlMapper;
    @Autowired
    private PushService doPush;

    @Override
    public int monitorRainfall() {
        try {
            WeatherDataModel weatherDataModel = weatherDataMapper.getNewestOne();
            if (!ObjectUtils.isEmpty(weatherDataModel)) {
                // 根据降雨量计算最低点和最高点海拔高度
                // 查询当前雨量是否超过阈值，超过则返回阈值信息，不超过返回空
                Float rainfalls = Float.valueOf(remoteUserService.selectConfigByKey("job.weather.rainfall").getMsg());
                // 判断雨量大小是否超过警戒值
                if (weatherDataModel.getRainVolum() >= rainfalls) {
                    Integer range = Integer.valueOf(remoteUserService.selectConfigByKey("job.weather.range").getMsg());
                    // 查询最低点车辆信息
                    DeviceInfoVo deviceInfoVo = deviceService.getLowestDevice();
                    Integer bottomPoint = deviceInfoVo.getAltitude();
                    // 如果超过警戒值则更新防碰撞系统所在高程最低的车辆向上30m内的所有车辆数据
                    Integer topPoint = bottomPoint + range;
                    // 批量插入设备告警数据
                    // 查询所有设备
                    List<DeviceInfoVo> deviceInfoVoList = deviceService.getAllDeviceInfoVo();
                    List<DeviceAlarmModel> deviceAlarmModelList = new ArrayList<>();
                    for (DeviceInfoVo deviceInfo : deviceInfoVoList) {
                        if (bottomPoint != 0 && topPoint != 0 && deviceInfo.getAltitude() != null) {
                            int floodState = deviceInfo.getAltitude() >= bottomPoint
                                    && deviceInfo.getAltitude() <= topPoint ? 1 : 0;
                            if (floodState > 0) {
                                Date date = new Date();
                                DeviceAlarmModel deviceAlarmModel = new DeviceAlarmModel();
                                deviceAlarmModel.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                                deviceAlarmModel.setDeviceId(deviceInfo.getId());
                                deviceAlarmModel.setDeviceName(deviceInfo.getDeviceName());
                                deviceAlarmModel.setDeviceType(CommonConstant.DEVICE_TYPE);
                                deviceAlarmModel.setCreateTime(date);
                                deviceAlarmModel.setFloodState(floodState);
                                deviceAlarmModelList.add(deviceAlarmModel);
                                executor.execute(() -> {
                                    //通过deviceName获取userId
                                    String userId = this.getUserIdByDeviceName(deviceInfo.getDeviceName());
                                    //插入业务告警主表
                                    Long id = this.insertAlarm(date, String.valueOf(weatherDataModel.getRainVolum()));
                                    //插入业务告警子表
                                    this.insertFloodAlarm(id, deviceInfo, date, userId);
                                    if(StringUtils.isNotEmpty(userId)){
                                        //推送消息提醒
                                        this.noticeInfo(deviceInfo.getDeviceName(), userId, date);
                                    }
                                });
                            }
                        }
                    }
                    if(deviceAlarmModelList.size()>0){
                        deviceService.saveBatchSql(deviceAlarmModelList);
                    }
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        return 1;
    }

    @Override
    public List<AlarmModel> selectAlarmList(AlarmModel alarmModel) {
        List<AlarmModel> list = floodControlMapper.selectAlarmList(alarmModel);
        for(AlarmModel am : list){
            am.setFloodAlarmList(this.getInfo(am.getId()));
        }
        return list;
    }

    /**
     * 获取防汛告警数据
     * @param zid 告警主表数据id
     * @return 结果集
     */
    public List<FloodAlarm> getInfo(Long zid) {
        List<FloodAlarm> list = floodControlMapper.selectFloodAlarmList(zid);
        for(FloodAlarm fa : list){
            if(fa.getUserId()!=null && !"".equals(fa.getUserId())){
                SysUser user = remoteUserService.getUserById(new Long(fa.getUserId())).getData();
                fa.setPhone(user.getPhonenumber());
                fa.setUserId(user.getNickName());
            }
        }
        return list;
    }

    /**
     * 新增告警主表数据
     * @param date 时间
     * @param rainVolum 数值
     * @return id
     */
    public Long insertAlarm(Date date, String rainVolum){
        AlarmModel am = new AlarmModel();
        am.setAlarmDate(date);
        am.setAlarmType("3");
        am.setAlarmValue(rainVolum);
        floodControlMapper.insertAlarm(am);
        return am.getId();
    }

    /**
     * 新增防汛告警数据
     * @param zid 告警主表id
     * @param deviceInfo 设备名称
     * @param date 时间
     * @param userId 人员id
     */
    public void insertFloodAlarm(Long zid, DeviceInfoVo deviceInfo, Date date, String userId){
        FloodAlarm fa = new FloodAlarm();
        fa.setZid(zid);
        fa.setDevice(deviceInfo.getDeviceName());
        fa.setAlarmDate(date);
        fa.setUserId(userId);
        fa.setLatitude(deviceInfo.getLatitude()+"");
        fa.setLongitude(deviceInfo.getLongitude()+"");
        fa.setAlarmContent("防汛告警: 设备名称: "+deviceInfo.getDeviceName()+",已处于危险区域。报警时间："+
                DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
        floodControlMapper.insertFlood(fa);
    }

    /**
     * 通过设备名称获取userId
     * @param deviceName 设备名称
     * @return userId
     */
    public String getUserIdByDeviceName(String deviceName){
        int account = weatherDataMapper.selectAccountByDeviceName(deviceName);
        if(account!=0){
            String userName =  String.format("%08d", account);
            R<LoginUser> loginUser = remoteUserService.getUserInfo(userName, SecurityConstants.INNER);
            if(loginUser!=null && loginUser.getData().getSysUser().getUserId()!=null){
                return loginUser.getData().getSysUser().getUserId().toString();
            }
        }
        return "";
    }

    /**
     * 推送消息
     */
    public void noticeInfo(String deviceName, String userId, Date date){
        SysNoticeInfo info = new SysNoticeInfo();
        info.setContent("设备名称: "+deviceName+",已处于危险区域。报警时间："+
                DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
        info.setTitle("防汛报警");
        info.setUserId(userId);
        info.setCreateBy(userId);
        info.setCreateTime(date);
        remoteNoticeInfoService.add(info);
        String cid = remoteUserService.getUserById(new Long(userId)).getData().getCid();
        Integer clientType = remoteUserService.getUserById(new Long(userId)).getData().getClientType();
        if(StringUtils.isNotEmpty(cid)){
            doPush.push(cid, "防汛报警","设备名称: "+deviceName+",已处于危险区域。报警时间："+
                    DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date),clientType);
        }
    }

}
